#ifndef PREPROCESSOR_H
#define PREPROCESSOR_H

#include "identifiimg.h"
#include "identtrackerorb.h"
#include "identtrackertemplate.h"
#include "imagerecord.h"
#include "source/precisionidentify.h"

#include <opencv2/imgproc.hpp>
#include <QObject>
#include <opencv2/core.hpp>
#include <QRect>
#include <QMutex>
#include <qreadwritelock.h>


class PreProcessor : public QObject
{
    Q_OBJECT


    Q_PROPERTY(QVariantList identImgRoi READ identImgRoi NOTIFY identImgRoiChanged)
    Q_PROPERTY(QVariantList monitorImgRoi READ monitorImgRoi NOTIFY monitorImgRoiChanged)
    Q_PROPERTY(float matchingsimilarity READ matchingsimilarity NOTIFY mmatchingsimilarityChanged)

    Q_PROPERTY(float scaleFactor READ scaleFactor WRITE setScaleFactor NOTIFY scaleFactorChanged)
    Q_PROPERTY(float fitThreshold READ fitThreshold WRITE setFitThreshold NOTIFY fitThresholdChanged)
    Q_PROPERTY(bool enableTracker READ enableTracker WRITE setEnableTracker NOTIFY enableTrackerChanged)
    Q_PROPERTY(bool offsetCompensation READ offsetCompensation WRITE setOffsetCompensation NOTIFY offsetCompensationChanged)
    Q_PROPERTY(bool enablePreTracking READ enablePreTracking WRITE setEnablePreTracking NOTIFY enablePreTrackingChanged)
    Q_PROPERTY(int optimalNumber READ optimalNumber WRITE setOptimalNumber NOTIFY optimalNumberChanged)
    Q_PROPERTY(int trackingAlgorithm READ trackingAlgorithm WRITE setTrackingAlgorithm NOTIFY trackingAlgorithmChanged)
    Q_PROPERTY(int precisionMatching READ precisionMatching WRITE setPrecisionMatching NOTIFY precisionMatchingChanged)
    Q_PROPERTY(int identifiThreshold READ identifiThreshold WRITE setIdentifiThreshold NOTIFY identifiThresholdChanged)
    Q_PROPERTY(bool identifiThresholdAuto READ identifiThresholdAuto WRITE setIdentifiThresholdAuto NOTIFY identifiThresholdAutoChanged)
    Q_PROPERTY(int boundaryThreshold READ boundaryThreshold WRITE setBoundaryThreshold NOTIFY boundaryThresholdChanged)
    //标识平滑
    Q_PROPERTY(float contourAreaMin READ contourAreaMin WRITE setcontourAreaMin NOTIFY contourAreaMinChanged)

public:
    static  PreProcessor &getInstance();

    Q_INVOKABLE void setMonitorROI(int x , int y ,int width ,int height);
    Q_INVOKABLE void setIdentifiROI(int x , int y ,int width ,int height);
    Q_INVOKABLE void resetMonitorROI();
    Q_INVOKABLE void resetIdentifiROI();

    Q_INVOKABLE void testAbort();

    QVariantList identImgRoi();
    QVariantList monitorImgRoi();
    float scaleFactor() const { return m_scaleFactor; }
    float fitThreshold() const { return m_fitThreshold; }
    bool enableTracker() const { return m_enableTracker; }
    bool offsetCompensation() const { return m_offsetCompensation; }
    bool enablePreTracking() const { return m_enablePreTracking; }
    int optimalNumber() const { return m_optimalNumber; }
    int trackingAlgorithm() const { return m_trackingAlgorithm; }
    int precisionMatching() const { return m_precisionMatching; }
    int identifiThreshold() const { return m_identifiThreshold; }
    bool identifiThresholdAuto() const { return m_identifiThresholdAuto; }
    int boundaryThreshold() const { return m_boundaryThreshold; }
    float matchingsimilarity() const {return m_matchingsimilarity;};

    void setRoiRect(const QVariantList &roiRect);
    void setScaleFactor(float scaleFactor);
    void setFitThreshold(float fitThreshold);
    void setEnableTracker(bool enable);
    void setOffsetCompensation(bool enable);
    void setEnablePreTracking(bool enable);
    void setOptimalNumber(int number);
    void setTrackingAlgorithm(int algorithm);
    void setPrecisionMatching(int matching);
    void setIdentifiThreshold(int threshold);
    void setIdentifiThresholdAuto(bool autoThreshold);
    void setBoundaryThreshold(int threshold);

    int contourAreaMin() const;
    void setcontourAreaMin(int contourAreaMin);

    void getBaseImage(cv::Mat &image);

    void processImg(ImageRecord &imgcard );
    void initializeTracker(int& trackerType);

    IdentifiImg identImg_;      //相较与相机
    IdentifiImg monitorImg_;    //相较与相机
    cv::Rect2d trackROI;

signals:
    void monitorRoiReset();
    void identifiRoiReset();

    void identImgRoiChanged();
    void monitorImgRoiChanged();
    void identImgChange(cv::Mat &img);
    void scaleFactorChanged();
    void fitThresholdChanged();
    void enableTrackerChanged();
    void offsetCompensationChanged();
    void enablePreTrackingChanged();
    void optimalNumberChanged();
    void trackingAlgorithmChanged();
    void precisionMatchingChanged();
    void identifiThresholdChanged();
    void identifiThresholdAutoChanged();
    void boundaryThresholdChanged();

    void mmatchingsimilarityChanged();
    void contourAreaMinChanged();

public slots:
    void cameraOpenFinish();
    void identifiImgImgChangeSlots(cv::Mat& img);
    void configDataChanged(const QString& category, const QString& key);
    void valueTableLoad();

private:
    PreProcessor(QObject *parent = nullptr);
    PreProcessor& operator=(const PreProcessor& rhs) = delete;

    QVariantList m_roiRect;
    float m_scaleFactor;
    float m_fitThreshold;
    bool m_enableTracker;
    bool m_offsetCompensation;
    bool m_enablePreTracking;
    int m_optimalNumber;
    int m_trackingAlgorithm;
    int m_precisionMatching;
    int m_identifiThreshold;
    bool m_identifiThresholdAuto;
    int m_boundaryThreshold;
    float m_matchingsimilarity;


    IdentTracker* identTracker_;


    int deviationX;  // x偏移，标识相较于模板
    int deviationY; // y偏移

    QVariantList saveMonitorImgROI;
    QVariantList saveIdentifiImgROI;

    QRect imageROI;
    void setIdentifiImg(cv::Mat img_);
    ~PreProcessor();

    QReadWriteLock mutex;
    QMutex trackerMutex;

    bool adjustROI(cv::Rect2d &roi, const cv::Size &imgSize);
    cv::Rect2d updateMonitorROI(const cv::Rect2d &identROI);
    bool initfirst = false ;
};

#endif // PREPROCESSOR_H



